/*
* Copyright (C) 2019 ~ 2021 Uniontech Software Technology Co.,Ltd.
*
* Author:     yanghongwei <yanghongwei@uniontech.com>
*
* Maintainer: yanghongwei <yanghongwei@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "tuogun_sensor_data.h"
#include "mysql_session.h"

#include <Poco/DateTimeFormatter.h>
#include <Poco/Data/Session.h>
#include <Poco/Exception.h>

#include <plog/Log.h>

using namespace Poco::Data;
using namespace Poco::Data::Keywords;

namespace Poco
{
    namespace Data
    {
        template<>
        class TypeHandler<struct TuogunSensorData>
        {
        public:
            static void bind(std::size_t pos, const TuogunSensorData &obj, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir) {
                // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
                // Note that we advance pos by the number of columns the datatype uses! For string/int this is one.
                poco_assert_dbg (!pBinder.isNull());
                TypeHandler<uint64_t>::bind(pos++, obj.id, pBinder, dir);
                TypeHandler<uint32_t>::bind(pos++, obj.sensor_id, pBinder, dir);
                TypeHandler<int32_t>::bind(pos++, obj.data, pBinder, dir);
                TypeHandler<Poco::DateTime>::bind(pos++, obj.create_time, pBinder, dir);
            }
            static void extract(std::size_t pos, TuogunSensorData &obj, const TuogunSensorData &defVal, AbstractExtractor::Ptr pExt) {
                // defVal is the default person we should use if we encunter NULL entries, so we take the individual fields
                // as defaults. You can do more complex checking, ie return defVal if only one single entry of the fields is null etc...
                poco_assert_dbg (!pExt.isNull());
                // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
                TypeHandler<uint64_t>::extract(pos++, obj.id, defVal.id, pExt);
                TypeHandler<uint32_t>::extract(pos++, obj.sensor_id, defVal.sensor_id, pExt);
                TypeHandler<int32_t>::extract(pos++, obj.data, defVal.data, pExt);
                TypeHandler<Poco::DateTime>::extract(pos++, obj.create_time, defVal.create_time, pExt);
            }
            static void prepare(std::size_t pos, const TuogunSensorData &obj, AbstractPreparator::Ptr pPreparator) {
                // the table is defined as Person (LastName VARCHAR(30), FirstName VARCHAR, Age INTEGER(3))
                poco_assert_dbg (!pPreparator.isNull());
                TypeHandler<uint64_t>::prepare(pos++, obj.id, pPreparator);
                TypeHandler<uint32_t>::prepare(pos++, obj.sensor_id, pPreparator);
                TypeHandler<int32_t>::prepare(pos++, obj.data, pPreparator);
                TypeHandler<Poco::DateTime>::prepare(pos++, obj.create_time, pPreparator);
            }
            static std::size_t size() { return 4; }
        };
    }
}

void printf(const TuogunSensorData &device)
{
    LOGD << "TuogunSensorData[id:" << device.id << " "
            << "sensor_id:" << device.sensor_id << " "
            << "data:" << device.data << " "
            << "create_time:" << Poco::DateTimeFormatter::format(device.create_time, Poco::DateTimeFormat::ISO8601_FORMAT) << "]";
}

std::vector<TuogunSensorData> TuogunSensorDataManager::getTuogunSensorDataBySensorId(uint32_t sensorId)
{
    std::vector<TuogunSensorData> ver_device;
    try {
        if (MysqlSession::Instance()->session()) {
            Statement query(*MysqlSession::Instance()->session());
            query << "SELECT * FROM tuogun_sensor_data WHERE sensor_id=? ORDER BY id DESC LIMIT 10",use(sensorId),into(ver_device),now;
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return ver_device;
}

TuogunSensorData TuogunSensorDataManager::getLastestTuogunSensorDataBySensorId(uint32_t sensorId)
{
    TuogunSensorData device;
    try {
        if (MysqlSession::Instance()->session()) {
            Statement query(*MysqlSession::Instance()->session());
            query << "SELECT * FROM tuogun_sensor_data WHERE sensor_id=? ORDER BY id DESC LIMIT 1",use(sensorId),into(device),now;
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return device;
}

std::vector<TuogunSensorData> TuogunSensorDataManager::getAllTuogunSensorData()
{
    std::vector<TuogunSensorData> ver_device;
    try {
        if (MysqlSession::Instance()->session()) {
            Statement query(*MysqlSession::Instance()->session());
            query << " SELECT * FROM tuogun_sensor_data",into(ver_device),now;

            for (auto device : ver_device)
                printf(device);
        }
    } catch (Poco::Exception &e) {
        LOGW << "exception : " << e.what();
    }
    return ver_device;
}
